package com.samehope.ar.component;

import com.samehope.ar.init.MappingContainer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.concurrent.atomic.AtomicLong;

/**
 * @Description: 版本号监控filter
 * @Author: ZhangLuo
 * @Email: 1946430@qq.com
 */
@Slf4j
@Component
public class VersionHandleFilter extends OncePerRequestFilter {

    @Autowired
    private MappingContainer mappingContainer;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {

        String versionHeader = request.getHeader("version");
        // 如果头部没有携带版本号, 或者版本号不是正整数, 直接停止请求
        if (versionHeader == null || !versionHeader.matches("[1-9]\\d*")) {
            response.setStatus(HttpStatus.NOT_FOUND.value());
            return ;
        }
        AtomicLong version = new AtomicLong(Long.valueOf(versionHeader));
        String versionSuffix = "/v" + version;

        // 版本降级策略, 先从当前请求版本开始查找, 直到最低版本, 如果都找不到, 返回404
        String requestURI = request.getRequestURI();
        String fullUri = "";
        boolean flag = false;
        while (version.get() > 0) {
            fullUri = requestURI + versionSuffix;
            flag = mappingContainer.exist(fullUri);
            if (flag) {
                break;
            }
            versionSuffix = "/v" + version.decrementAndGet();
        }

        if (flag) {
            response.setCharacterEncoding("UTF-8");
            request.getRequestDispatcher(fullUri).forward(request, response);
            return;
        } else {
            response.setStatus(HttpStatus.NOT_FOUND.value());
            return;
        }
    }
}
